<?php

namespace Henan\ThinkSdk\helper;


use Exception;
use think\db\ConnectionInterface;
use think\facade\Config;
use think\facade\Db;

/**
 * 模型操作类
 * @author henan
 */
class MD
{
    /**
     * 获取临时数据库连接对象
     * @param string $hostname
     * @param string $database
     * @param string $user
     * @param string $password
     * @return ConnectionInterface
     * @throws Exception
     */
    public static function content(string $hostname, string $database, string $user, string $password): ConnectionInterface
    {
        try {
            $config = Config::get('database');
            $config['connections']['temp'] = [
                'type' => 'mysql',
                'hostname' => $hostname,
                'database' => $database,
                'username' => $user,
                'password' => $password,
                'hostport' => 3306,
                'params' => [],
                'charset' => 'utf8mb4'
            ];
            Config::set($config, 'database');
            $content = Db::connect('temp', true);
            $content->query('SELECT VERSION()');
        } catch (\Exception $e) {
            throw new Exception($e->getMessage());
        }
        return $content;
    }

    /**
     * 两个ids逗号分隔取交集查询
     * @param string $className 模型
     * @param string $field 关联字段
     * @param array $ids 多对多关联id数组
     * @return mixed
     * @throws Exception
     */
    public static function whereRawConcat(string $className, string $field, array $ids): mixed
    {
        try {
            return (new $className())->whereRaw("concat(',',{$field},',') regexp concat(',(',replace(?,',','|'),'),')", [implode(',', $ids)]);
        } catch (Exception $e) {
            throw new Exception($e->getMessage());
        }
    }

    /**
     * 判断是否为关联数组
     * @param $array
     * @return bool
     */
    private static function isAssociativeArray($array): bool
    {
        if (!is_array($array)) {
            return false; // 确保变量是数组
        }
        $keys = array_keys($array);
        return array_keys($keys) !== $keys;
    }

    /**
     * 构建查询条件
     * @param array $data 数据
     * @param array $fields 指定查询字段
     * @return array
     * @throws Exception
     */
    private static function buildWhere(array $data, array $fields = []): array
    {
        $where = [];
        if (!self::isAssociativeArray($data)) {
            throw new Exception('数据必须是关联数组');
        }
        if ($fields) {
            foreach ($fields as $field) {
                isset($data[$field]) && $where[] = [$field, '=', $data[$field]];
            }
        } else {
            foreach ($data as $field => $value) {
                $where[] = [$field, '=', $value];
            }
        }
        return $where;
    }

    /**
     * 如果不存在则保存
     * @param string $model 模型名称
     * @param array $data 数据
     * @param array $uniqueFields 唯一字段
     * @return mixed
     * @throws Exception
     */
    public static function saveNotExist(string $model, array $data, array $uniqueFields = []): mixed
    {
        try {
            $row = (new $model())->where(self::buildWhere($data, $uniqueFields))->find();
            if (empty($row)) {
                $row = (new $model())->create($data);
                return (new $model())->find($row->id);
            } else {
                return $row;
            }
        } catch (\Exception $e) {
            throw new Exception($e->getMessage());
        }
    }

    /**
     * 保存或更新数据
     * @param string $model 模型名
     * @param array $data 保存数据
     * @param array $uniqueFields 唯一字段
     * @return mixed
     * @throws Exception
     */
    public static function saveOrUpdate(string $model, array $data = [], array $uniqueFields = []): mixed
    {
        try {
            $row = (new $model())->where(self::buildWhere($data, $uniqueFields))->find();
            if (empty($row)) {
                $row = (new $model())->create($data);
                return (new $model())->find($row->id);
            } else {
                $row->save($data);
                return $row;
            }
        } catch (\Exception $e) {
            throw new Exception($e->getMessage());
        }
    }
}